import { Injector } from '@angular/core';
import { FarrisDesignBaseComponent, IControlService } from '@farris/designer-element';
import { DesignerEnvType, DgControl, DomService, FormBasicService, RefreshFormService } from '@farris/designer-services';
import { ControlService } from '../../../../../service/control.service';
import { IdService } from '@farris/ui-common';
import { MessagerService } from '@farris/ui-messager';
import { ControlContextMenuItem } from '../../../../../entity/control-context-menu';
import { cloneDeep } from 'lodash-es';

const CHANGE_FORM_TO_TABLE_MENU = 'changeFormToTableComponent';

/**
 * Form组件切换为table组件
 */
export class TableComponentCreatorContextMenuService {
    private domService: DomService;
    private messagerService: MessagerService;
    public refreshFormService: RefreshFormService;
    private controlService: IControlService;

    private cmpInstance: FarrisDesignBaseComponent;

    constructor(private injector: Injector, cmpInstance: FarrisDesignBaseComponent) {

        this.domService = this.injector.get(DomService);
        this.refreshFormService = this.injector.get(RefreshFormService);
        this.messagerService = this.injector.get(MessagerService);
        this.controlService = this.injector.get(ControlService);

        this.cmpInstance = cmpInstance;
    }


    /**
     * 组装form切换为table的菜单
     * @param menuConfig 菜单配置
     */
    assembleChangeFormToTableMenu(menuConfig: ControlContextMenuItem[]): ControlContextMenuItem[] {

        const canChange = this.checkCanChangeToTableComponent();
        if (!canChange) {
            menuConfig = menuConfig.filter(menu => menu.id !== CHANGE_FORM_TO_TABLE_MENU);
        }
        return menuConfig;

    }

    /**
     * 校验当前组件是否支持由Form类型切换为Table类型
     */
    checkCanChangeToTableComponent() {
        // 目前只在零代码环境提供切换功能
        const formBasicService = this.injector.get(FormBasicService);
        if (formBasicService.envType !== DesignerEnvType.noCode) {
            return;
        }
        const formCmp = this.cmpInstance.component;

        // 1、只支持form组件
        if (!formCmp.componentType || !formCmp.componentType.includes('form') || !formCmp.contents || !formCmp.contents.length) {
            return;
        }
        // 2、组件内不能有table控件
        const table = this.domService.selectNode(formCmp, item => item.type === DgControl.Table.type);
        if (table) {
            return;
        }

        // 3、组件结构必须满足：Component-Section-Form三层结构
        const section = formCmp.contents[0];
        const form = section && section.contents && section.contents.length && section.contents[0];
        if (!section || section.type !== DgControl.Section.type || !form || form.type !== DgControl.Form.type) {
            return;
        }

        // 4、Section 和Form必须包含标准样式
        const sectionCls = section.appearance && section.appearance.class || '';
        const formCls = form.appearance && form.appearance.class || '';
        if (!sectionCls.includes('f-section-form') || !formCls.includes('f-form-layout')) {
            return;
        }

        // 6、检测form中是否包含未绑定字段的控件，若有，认为不是标准的form，不支持转为table
        let hasUnBindingControl = false;
        for (const control of form.contents) {
            if (control && control.type === DgControl.FieldSet.type) {
                continue;
            }
            if (!control || !control.binding || !control.binding.field) {
                hasUnBindingControl = true;
                break;
            }
        }
        if (hasUnBindingControl) {
            return;
        }

        return true;
    }

    changeFormComponentToTableComponent() {
        this.messagerService.question('当前区域内控件将以表格形式展示，此操作不可撤销，确定切换？', () => {
            this.confirmChangeFormComponentToTableComponent();
        });
    }
    /**
     * 由Form切换为table
     */
    confirmChangeFormComponentToTableComponent() {

        const form = this.domService.selectNode(this.cmpInstance.component, item => item.type === DgControl.Form.type);
        if (!form) {
            return;
        }
        // 1、修改component组件类型
        this.cmpInstance.component.componentType = 'table';

        // 2、Section、form控件增加样式
        const section = this.cmpInstance.component.contents[0];
        section.appearance.class = section.appearance.class.replace('f-section-form', 'f-section-card-table');
        form.appearance.class += ' f-table-has-form';

        // 3、创建table控件
        const table = this.controlService.getControlMetaData(DgControl.Table.type);
        table.id = `${form.id}_table`;
        table.devMode = 'simple';
        table.rows = [];

        // 4、组装table单元格
        const plainControlList = this.splitControlsByFieldSet(form.contents);
        plainControlList.forEach(controlList => {
            if (controlList && controlList.length) {
                const rows = this.resoloveTableRows(controlList, table.devMode);
                table.rows = table.rows.concat(rows);
            }
        });

        // 5、将table放在form下
        form.contents = [table];

        // 6、刷新表单
        this.cmpInstance.emit('clearPropertyPanel');
        this.refreshFormService.refreshFormDesigner.next();
    }

    /**
     * 卡片区域内的控件若有分组FieldSet，需要根据分组划分前后区域，分组的起点控件需要在table内单独起一行
     */
    private splitControlsByFieldSet(controlList: any[], groupIndex = 0) {
        const plainControlList = [];

        controlList.forEach(co => {
            if (co.type === DgControl.FieldSet.type && co.contents && co.contents.length) {
                groupIndex++;
                if (!plainControlList[groupIndex]) {
                    plainControlList[groupIndex] = [];
                }
                plainControlList[groupIndex] = co.contents;

                groupIndex++;
            } else {
                if (!plainControlList[groupIndex]) {
                    plainControlList[groupIndex] = [];
                }
                plainControlList[groupIndex].push(co);
            }

        });

        return plainControlList;
    }

    /**
     * 组装表格
     * @param controlList 控件列表
     * @param devMode 展示模式
     */
    resoloveTableRows(controlList: any[], devMode: string): any[] {
        const idService = this.injector.get(IdService);
        const rows = [];
        // 计算行数
        const rowCounts = this.getTableRowCounts(controlList);

        for (let rowIndex = 0, fieldCount = 0; rowIndex < rowCounts; rowIndex++) {
            let columns: any[] = [];
            for (let index = 0; index < 2; index++) {
                const groupId = idService.generate();
                const originalControl = fieldCount < controlList.length ? controlList[fieldCount] : null;

                let labelTds;
                let editorTds;

                // 第二列单元格是通栏控件：需要创建空白单元格（显示，不绑定字段）
                if (index === 1 && this.checkIfCrossColumn(originalControl)) {
                    labelTds = this.createLabelTd(null, devMode, groupId);
                    editorTds = this.createEditorTd(null, devMode, groupId);

                } else {
                    // 普通单元格：正常绑定字段
                    labelTds = this.createLabelTd(originalControl, devMode, groupId);
                    editorTds = this.createEditorTd(originalControl, devMode, groupId);

                    fieldCount++;
                }
                columns = columns.concat(labelTds).concat(editorTds);


                // 第一列单元格是通栏控件：需要创建空白单元格（不显示，不绑定字段）
                if (index === 0 && this.checkIfCrossColumn(originalControl)) {
                    const invisibleTds = this.createInvisibleTd(devMode, groupId);
                    columns = columns.concat(invisibleTds);

                    editorTds[0].colspan = 5;
                    editorTds[0].markCol = 0;
                    editorTds[0].markRow = 0;

                    index++;
                }

            }

            rows.push({
                id: idService.generate(),
                type: 'TableRow',
                columns
            });

        }

        return rows;
    }
    /**
     * 计算table行数。
     * 规则：一行两个字段；若控件class='col-12'，则占通栏，其余都是默认一个单元格，
     * @param controlList 输入控件列表
     */
    private getTableRowCounts(controlList: any[]) {
        // 单元格总数
        let columnCount = 0;

        // tslint:disable-next-line: prefer-for-of
        for (let controlIndex = 0; controlIndex < controlList.length; controlIndex++) {
            const control = controlList[controlIndex];
            const nextControl = controlIndex + 1 < controlList.length ? controlList[controlIndex + 1] : null;

            const isFirstColumn = controlIndex % 2 === 0;
            const isCrossColumn = this.checkIfCrossColumn(control);
            const selfColumnCount = isCrossColumn ? 2 : 1;

            // 第一列控件不通栏，但是下一个控件是通栏的，这种场景下需要补充空白单元格
            if (isFirstColumn && !isCrossColumn && this.checkIfCrossColumn(nextControl)) {
                columnCount += selfColumnCount + 1;
            } else {
                columnCount += selfColumnCount;
            }

        }

        // 求行数
        const rowCount = columnCount / 2 + 0.5;

        return parseInt(rowCount + '', 10);
    }

    /**
     * 检查单元格是否为通栏
     * @param control 控件
     */
    private checkIfCrossColumn(control: any) {
        let controlClass = control && control.appearance && control.appearance.class || '';
        controlClass = controlClass.trim();
        if (controlClass === 'col-12' || controlClass === 'col-12 col-md-12 col-xl-12 col-el-12') {
            return true;
        }
        // const colClassItems = controlClass.split(' ');

        // const originColClass = colClassItems.find(item => /^col-([1-9]|10|11|12)$/.test(item));
        // const originColMDClass = colClassItems.find(item => /^col-md-([1-9]|10|11|12)$/.test(item));
        // const originColXLClass = colClassItems.find(item => /^col-xl-([1-9]|10|11|12)$/.test(item));
        // const originColELClass = colClassItems.find(item => /^col-el-([1-9]|10|11|12)$/.test(item));

        // const colColumn = originColClass && originColClass.replace('col-', '');
        // const colMdColumn = originColMDClass && originColMDClass.replace('col-md-', '');
        // const colXLColumn = originColXLClass && originColXLClass.replace('col-xl-', '');
        // const colELColumn = originColELClass && originColELClass.replace('col-el-', '');

    }
    /**
     * 创建标签类单元格
     * @param cardControl 卡片组件内的控件结构
     */
    private createLabelTd(cardControl: any, devMode = 'advanced', groupId: string): any[] {
        const idService = this.injector.get(IdService);
        const tdMetadata = this.controlService.getControlMetaData('TableTd');
        if (!tdMetadata) {
            return [];
        }
        tdMetadata.tdType = 'staticText';
        tdMetadata.appearance.class = 'farris-group-wrap--label';
        tdMetadata.id = idService.generate();

        if (cardControl) {
            tdMetadata.staticText.text = cardControl.title;
            tdMetadata.staticText.require = cardControl.require;
        }

        // 简单类单元格需要赋值分组id
        if (devMode === 'simple') {
            tdMetadata.groupId = groupId;
        }
        return [tdMetadata];
    }

    /**
     * 创建编辑器类单元格
     * @param field schema字段
     */
    private createEditorTd(cardControl: any, devMode = 'advanced', groupId: string) {
        const idService = this.injector.get(IdService);

        // 合并单元格
        const tdMetadata = this.controlService.getControlMetaData('TableTd');
        tdMetadata.id = idService.generate();
        tdMetadata.tdType = 'editor';
        tdMetadata.colspan = 2;
        tdMetadata.appearance.class = 'farris-group-wrap--input';

        if (cardControl) {
            const editorMetadata = cloneDeep(cardControl);
            editorMetadata.showInTable = true;
            editorMetadata.appearance = { class: '' };
            tdMetadata.editor = editorMetadata;
        }

        // 隐藏单元格
        const invisibleTd = this.controlService.getControlMetaData('TableTd');
        invisibleTd.id = idService.generate();
        invisibleTd.invisible = true;
        invisibleTd.markCol = 1;
        invisibleTd.markRow = 0;

        // 简单类单元格需要赋值分组id
        if (devMode === 'simple') {
            tdMetadata.groupId = groupId;
            invisibleTd.groupId = groupId;
        }

        return [tdMetadata, invisibleTd];

    }
    /**
     * 创建隐藏单元格，用于创建通栏的控件中，右侧隐藏的3个单元格
     */
    createInvisibleTd(devMode = 'advanced', groupId: string) {

        const staticTextTd = this.createLabelTd(null, devMode, groupId)[0];
        staticTextTd.invisible = true;
        staticTextTd.markCol = 2;
        staticTextTd.markRow = 0;


        const editorTds = this.createEditorTd(null, devMode, groupId);
        const editorTd = editorTds[0];
        editorTd.invisible = true;
        editorTd.markCol = 3;
        editorTd.markRow = 0;

        const invisibleEditorTd = editorTds[1];
        invisibleEditorTd.invisible = true;
        invisibleEditorTd.markCol = 4;
        invisibleEditorTd.markRow = 0;

        return [staticTextTd, editorTd, invisibleEditorTd];
    }

}
